"""
格式化合法的权限和菜单并保存在session中
"""
from django.conf import settings

from oracle.models import OMenu
from oracle.base.basemodel import DEFAULT_NAME, DEFAULT_DETAIL, DEFAULT_AVATAR


def menu_build(menu_dict, current_menu_id):
    """
    构建多级菜单字典数据
    :param menu_dict: 菜单字典
    :param current_menu_id: 当前有权限的菜单id
    :return:
    """
    # 如果菜单项已经存在，则直接返回，不占用查询资源
    if menu_dict.get(str(current_menu_id)):
        return True
    # 菜单数据集合
    current_menu_id = int(current_menu_id)
    menu_queryset = OMenu.objects.filter(id=current_menu_id, status=0) \
        .values('id', 'title', 'menu_icon', 'link_to_permission__url', 'menu_inner', 'parent', 'level')
    # 如果有菜单数据
    if menu_queryset:
        # 当前菜单属性
        menu_obj = menu_queryset[0]

        node_id = str(menu_obj['id'])
        # 以id为key在菜单字典中获取value
        # 如果没有则插入当前项到菜单字典中
        node = menu_dict.setdefault(node_id, dict())
        # 菜单字典赋值
        node['title'] = menu_obj['title']
        node['icon'] = menu_obj['menu_icon']
        node['url'] = menu_obj['link_to_permission__url']
        node['level'] = menu_obj['level']
        # 页面内菜单列表
        node.setdefault("inner", list())
        # 子菜单列表
        node.setdefault("children", list())

        # 判断是页面内菜单列表
        if menu_obj['menu_inner']:
            # 有权限才有加入菜单字典的意义
            if menu_obj['link_to_permission__url']:
                # 获取menu_inner_parent的数值
                menu_inner = str(menu_obj['menu_inner'])
                # 记录父节点id 为判断展开菜单提供依据
                node['inner_parent'] = menu_inner

                # 如果没有对应的parent数值，则递归函数，直到查找到这一支的顶级菜单项为止
                if menu_inner not in menu_dict:
                    menu_build(menu_dict, menu_inner)
                # 获取上级菜单项，将本支添加到子节点中
                menu_inner = menu_dict.get(menu_inner)
                # TODO 逻辑上inner_parent不能有children并且不能有url，应该添加程序确认。优化或者有bug时再考虑
                menu_inner['inner'].append(node_id)
        # 如果有parent, 是次级菜单
        elif menu_obj['parent']:
            # 获取parent的数值
            menu_parent = str(menu_obj['parent'])
            # 记录父节点id 为判断展开菜单提供依据
            node['parent'] = menu_parent

            # 如果没有对应的parent数值，则递归函数，直到查找到这一支的顶级菜单项为止
            if menu_parent not in menu_dict:
                menu_build(menu_dict, menu_parent)
            # 获取上级菜单项，将本支添加到子节点中
            menu_parent = menu_dict.get(menu_parent)
            menu_parent['children'].append(node_id)
            # TODO 逻辑上有权限不能有子菜单，需要程序判断，优化或者有bug时再考虑
            # 有权限不能有子菜单
            # if menu_obj['link_to_permission__url']:
            #     node["children"] = None
        else:
            # 顶级菜单加入到根
            menu_dict["root"]["children"].append(node_id)
            # TODO 逻辑上有权限不能有子菜单，需要程序判断，优化或者有bug时再考虑
            # 有权限不能有子菜单
            # if menu_obj['link_to_permission__url']:
            #     node["children"] = None
        return True
    else:
        # 数据库中没有找到对应记录
        return False


def init_handler(request, current_users, user_info=None, *args, **kwargs):
    """
    用户权限以及菜单初始化
    :param request: 请求相关所有数据
    :param current_users: 当前用户对象，可迭代对象
        如果有单独认证，用户可能属于多个组等，就可能会传入多个组或者角色等，为了兼容，定义传入为可迭代对象
    :param user_info: 用户显示信息，需要包含以下几个内容
        show_name: 显示名字
        show_detail: 显示简介
        show_avatar: 显示头像
    :param args:
    :param kwargs:
    :return: 返回构建结果是否有问题
    """
    if user_info is None:
        user_info = {
            "show_name": DEFAULT_NAME,
            "show_detail": DEFAULT_DETAIL,
            "show_avatar": DEFAULT_AVATAR,
        }
    permissions_list = list()
    for current_user in current_users:
        # 根据用户信息获取用户所有权限和菜单信息，并放入session
        permissions_queryset = current_user.roles.filter(permissions__isnull=False, status=0).values(
            'permissions__id',
            'permissions__url',
            'permissions__name',
            'permissions__omenu__id',
        ).distinct()
        # 每一个获取的权限集合都进行保存
        permissions_list.append(permissions_queryset)
    # 获取权限中所有的url
    permissions_dict = dict()
    # 菜单树形字典，首先定义根节点以及已经点击菜单列表
    menu_dict = {"root": {"children": list()}, "active": list()}
    # 权限以及菜单构建结果标志
    flag = True
    # 循环所有的权限集合
    for permissions_queryset in permissions_list:
        # 循环权限集合
        for item in permissions_queryset:
            key = item['permissions__name']
            value = {'id': item['permissions__id'], 'url': item['permissions__url'], }
            # 如果存在则跳过赋值，如果不存在则进行赋值操作
            # 最终所有的权限信息都存储在permissions_dict字典里面
            permissions_dict.setdefault(key, value)
            # 不是菜单则不再处理继续循环
            if not item['permissions__omenu__id']:
                continue
            # 构建菜单
            result = menu_build(menu_dict, item['permissions__omenu__id'])
            if not result:
                # 菜单构建有问题
                flag = False
    # session存储
    request.session[settings.PERMISSION_SESSION_KEY] = permissions_dict
    request.session[settings.MENU_SESSION_KEY] = menu_dict
    request.session["oracle_user"] = user_info
    request.session["oracle_users_list"] = list()
    for user in current_users:
        request.session["oracle_users_list"].append({
            "key": user.key,
            "id": user.id,
        })
    # 设定6个小时的过期时间(6 * 60 * 60)
    request.session['_session_expiry'] = 21600
    # 返回构建结果
    return flag
